Synchromize libiberty sources with master version in gcc repository
authorNick Clifton <nickc@redhat.com>
Mon, 26 Jun 2023 14:47:15 +0000 (15:47 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 26 Jun 2023 14:47:15 +0000 (15:47 +0100)
libiberty/ChangeLog
libiberty/argv.c
libiberty/configure
libiberty/configure.ac
libiberty/cp-demangle.c
libiberty/lrealpath.c
libiberty/make-temp-file.c
libiberty/obstacks.texi
libiberty/pex-win32.c
libiberty/strstr.c
libiberty/testsuite/demangle-expected

index 0e2289d81b733b5ddfcfd737be303c0cf2a3b402..3424fef99ba2a19bd7bb3fc7dfa7805882307a3a 100644 (file)
@@ -1,3 +1,72 @@
+2023-06-15  Marek Polacek  <polacek@redhat.com>
+
+       * configure.ac: Also set shared when enable_host_pie.
+       * configure: Regenerate.
+
+2023-06-13  Nathan Sidwell  <nathan@acm.org>
+
+       * cp-demangle.c (d_print_conversion): Remove incorrect
+       template instantiation handling.
+       * testsuite/demangle-expected: Add testcases.
+
+2023-06-07  Costas Argyris  <costas.argyris@gmail.com>
+
+       * argv.c (writeargv): Constant propagate "0" for "status",
+       simplifying the code slightly.
+
+2023-06-06  Costas Argyris  <costas.argyris@gmail.com>
+
+       * argv.c (writeargv): Simplify & remove gotos.
+
+2023-06-05  Costas Argyris  <costas.argyris@gmail.com>
+
+       * pex-win32.c: fix typos.
+
+2023-06-05  Costas Argyris  <costas.argyris@gmail.com>
+
+       * pex-win32.c (win32_spawn): Check command line length
+       and generate a response file if necessary.
+       (spawn_script): Adjust parameters.
+       (pex_win32_exec_child): Ditto.
+
+2023-06-03  Patrick Palka  <ppalka@redhat.com>
+
+       PR c++/70790
+       * cp-demangle.c (cplus_demangle_operators): Add the noexcept
+       operator.
+       (d_print_comp_inner) <case DEMANGLE_COMPONENT_UNARY>: Always
+       print parens around the operand of noexcept too.
+       * testsuite/demangle-expected: Test noexcept operator
+       demangling.
+
+2023-04-02  Jakub Jelinek  <jakub@redhat.com>
+
+       PR other/109306
+       * strstr.c: Revert the 2020-11-13 changes.
+       (strstr): Return s1 if len is 0.
+
+2023-03-30  Gerald Pfeifer  <gerald@pfeifer.com>
+
+       * obstacks.texi (Preparing for Obstacks): Remove a (broken)
+       reference to the Glibc manual.
+
+2023-03-03  Costas Argyris  <costas.argyris@gmail.com>
+
+       * pex-win32.c (win32_spawn): Fix memory leak of cmdline
+       buffer and refactor to have cleanup code appear once
+       for all exit cases.
+
+2023-02-11  niXman  <i.nixman@autistici.org>
+
+       * lrealpath.c (lrealpath): try to resolve symlink and
+       use UNC paths where applicable.
+
+2023-01-07  LIU Hao  <lh_mouse@126.com>
+
+       PR middle-end/108300
+       * make-temp-file.c: Define `WIN32_LEAN_AND_MEAN` before <windows.h>.
+       * pex-win32.c: Likewise.
+
 2022-11-23  Marek Polacek  <polacek@redhat.com>
 
        Revert:
index a95a10e14ff44c9a0d4499fc91a40ccb68244417..c2823d3e4ba85121a3240aff63fdaf4f2679d906 100644 (file)
@@ -289,8 +289,8 @@ char **buildargv (const char *input)
 @deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
 
 Write each member of ARGV, handling all necessary quoting, to the file
-named by FILE, separated by whitespace.  Return 0 on success, non-zero
-if an error occurred while writing to FILE.
+associated with FILE, separated by whitespace.  Return 0 on success,
+non-zero if an error occurred while writing to FILE.
 
 @end deftypefn
 
@@ -299,8 +299,6 @@ if an error occurred while writing to FILE.
 int
 writeargv (char * const *argv, FILE *f)
 {
-  int status = 0;
-
   if (f == NULL)
     return 1;
 
@@ -314,37 +312,26 @@ writeargv (char * const *argv, FILE *f)
 
           if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
             if (EOF == fputc ('\\', f))
-              {
-                status = 1;
-                goto done;
-              }
+              return 1;
 
           if (EOF == fputc (c, f))
-            {
-              status = 1;
-              goto done;
-            }
+            return 1;
+         
           arg++;
         }
 
       /* Write out a pair of quotes for an empty argument.  */
       if (arg == *argv)
-       if (EOF == fputs ("\"\"", f))
-         {
-           status = 1;
-           goto done;
-         }
+        if (EOF == fputs ("\"\"", f))
+          return 1;
 
       if (EOF == fputc ('\n', f))
-        {
-          status = 1;
-          goto done;
-        }
+        return 1;
+      
       argv++;
     }
 
- done:
-  return status;
+  return 0;
 }
 
 /*
index 1ccfac9fb11f334926f253d284b03a8335d94b2e..dd896270dc63bc3a28263f24efbe758cad44259f 100755 (executable)
@@ -5396,8 +5396,8 @@ case "${enable_shared}" in
   *) shared=yes ;;
 esac
 
-# ...unless --enable-host-shared was passed from top-level config:
-if [ "${enable_host_shared}" = "yes" ]; then
+# ...unless --enable-host-{shared,pie} was passed from top-level config:
+if [ "${enable_host_shared}" = "yes" ] || [ "${enable_host_pie}" = "yes" ]; then
   shared=yes
 fi
 
index 6c1ff9c60933a95a150334652061cd649457eebc..0748c592704abb836d3ad4935a1b853c51425c4f 100644 (file)
@@ -245,8 +245,8 @@ case "${enable_shared}" in
   *) shared=yes ;;
 esac
 
-# ...unless --enable-host-shared was passed from top-level config:
-if [[ "${enable_host_shared}" = "yes" ]]; then
+# ...unless --enable-host-{shared,pie} was passed from top-level config:
+if [[ "${enable_host_shared}" = "yes" ]] || [[ "${enable_host_pie}" = "yes" ]]; then
   shared=yes
 fi
 
index f2b36bcad68bb45e852b315bf2e0446949c1ca58..3bd303a7544581ac77a7106f64244de9edde0c2e 100644 (file)
@@ -1947,6 +1947,7 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "ng", NL ("-"),         1 },
   { "nt", NL ("!"),         1 },
   { "nw", NL ("new"),       3 },
+  { "nx", NL ("noexcept"),  1 },
   { "oR", NL ("|="),        2 },
   { "oo", NL ("||"),        2 },
   { "or", NL ("|"),         2 },
@@ -5836,8 +5837,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
        if (code && !strcmp (code, "gs"))
          /* Avoid parens after '::'.  */
          d_print_comp (dpi, options, operand);
-       else if (code && !strcmp (code, "st"))
-         /* Always print parens for sizeof (type).  */
+       else if (code && (!strcmp (code, "st") || !strcmp (code, "nx")))
+         /* Always print parens for sizeof (type) and noexcept(expr).  */
          {
            d_append_char (dpi, '(');
            d_print_comp (dpi, options, operand);
@@ -6659,32 +6660,10 @@ d_print_conversion (struct d_print_info *dpi, int options,
       dpt.template_decl = dpi->current_template;
     }
 
-  if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
-    {
-      d_print_comp (dpi, options, d_left (dc));
-      if (dpi->current_template != NULL)
-       dpi->templates = dpt.next;
-    }
-  else
-    {
-      d_print_comp (dpi, options, d_left (d_left (dc)));
-
-      /* For a templated cast operator, we need to remove the template
-        parameters from scope after printing the operator name,
-        so we need to handle the template printing here.  */
-      if (dpi->current_template != NULL)
-       dpi->templates = dpt.next;
+  d_print_comp (dpi, options, d_left (dc));
 
-      if (d_last_char (dpi) == '<')
-       d_append_char (dpi, ' ');
-      d_append_char (dpi, '<');
-      d_print_comp (dpi, options, d_right (d_left (dc)));
-      /* Avoid generating two consecutive '>' characters, to avoid
-        the C++ syntactic ambiguity.  */
-      if (d_last_char (dpi) == '>')
-       d_append_char (dpi, ' ');
-      d_append_char (dpi, '>');
-    }
+  if (dpi->current_template != NULL)
+    dpi->templates = dpt.next;
 }
 
 /* Initialize the information structure we use to pass around
index c662f8fd37edf9e1fe21b2670ef4bf1f555da365..2578288e8acef49d0f4ac624fdc81dfbff7befce 100644 (file)
@@ -68,8 +68,135 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include <windows.h> /* for GetFullPathName */
-# endif
+#  include <windows.h> /* for GetFullPathName/GetFinalPathNameByHandle/
+                          CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+     for (unsigned i = 0; i != (_len); ++i) \
+       if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the man: `If the lpBuffer buffer is too small to contain
+     the path, the return value is the size, in TCHARs, of the buffer
+     that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+    return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+     from the  man: `If the function fails because lpszFilePath is too
+     small to hold the string plus the terminating null character,
+     the return value is the required buffer size, in TCHARs. This
+     value _includes_the_size_of_the_terminating_null_character_`.
+     but in my testcase I have path with 26 chars, the function
+     returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,NULL
+    ,0
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+    return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+     fh
+    ,buf
+    ,len
+    ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+    ? (WIN32_UNC_PREFIX_LEN - 2)
+    : WIN32_IS_NON_UNC_PREFIX(buf)
+      ? WIN32_NON_UNC_PREFIX_LEN
+      : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+    ptr[0] = '/';
+    ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +255,52 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
-     don't have symlinks and just canonicalize to a Windows absolute
-     path.  GetFullPath converts ../ and ./ in relative paths to
-     absolute paths, filling in current drive if one is not given
-     or using the current directory of a specified drive (eg, "E:foo").
-     It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-    char buf[MAX_PATH];
-    char* basename;
-    DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename);
-    if (len == 0 || len > MAX_PATH - 1)
-      return strdup (filename);
-    else
-      {
-       /* The file system is case-preserving but case-insensitive,
-          Canonicalize to lowercase, using the codepage associated
-          with the process locale.  */
-        CharLowerBuff (buf, len);
-        return strdup (buf);
-      }
-  }
-#endif
+    char *res;
+
+    /* For Windows Vista and greater */
+#if _WIN32_WINNT >= 0x0600
+
+    /* For some reason the function receives just empty `filename`, but not NULL.
+       What should we do in that case?
+       According to `strdup()` implementation
+         (https://elixir.bootlin.com/glibc/latest/source/string/strdup.c)
+       it will alloc 1 byte even for empty but non NULL string.
+       OK, will use `strdup()` for that case.
+    */
+    if ( 0 == strlen(filename) )
+      return strdup(filename);
+
+    HANDLE fh = CreateFile(
+       filename
+      ,FILE_READ_ATTRIBUTES
+      ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
+      ,NULL
+      ,OPEN_EXISTING
+      ,FILE_FLAG_BACKUP_SEMANTICS
+      ,NULL
+    );
+
+    if ( fh == INVALID_HANDLE_VALUE ) {
+      res = get_full_path_name(filename);
+    } else {
+      res = get_final_path_name(fh);
+      CloseHandle(fh);
 
-  /* This system is a lost cause, just duplicate the filename.  */
-  return strdup (filename);
+      if ( !res )
+        res = get_full_path_name(filename);
+    }
+
+#else
+
+    /* For Windows XP */
+    res = get_full_path_name(filename);
+
+#endif // _WIN32_WINNT >= 0x0600
+
+    return res;
+  }
+#endif // _WIN32
 }
index fae743f398539d5217bcaca5f1a3de7be9f9e547..1d2f21d6c5cb2e14c66354b6bbfe62c362233b8a 100644 (file)
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
 #endif
 #if defined(_WIN32) && !defined(__CYGWIN__)
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 #if HAVE_SYS_STAT_H
index b2d2403210bb7de78344ebeb8d8b55e40e31d61d..37d26c90f1b81c3488b2b4f35c883b15487d27a2 100644 (file)
@@ -172,8 +172,8 @@ The value of this variable is a pointer to a function that
 @code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate
 memory.  The default action is to print a message and abort.
 You should supply a function that either calls @code{exit}
-(@pxref{Program Termination, , , libc, The GNU C Library Reference Manual}) or @code{longjmp} (@pxref{Non-Local
-Exits, , , libc, The GNU C Library Reference Manual}) and doesn't return.
+(@pxref{Program Termination, , , libc, The GNU C Library Reference Manual}) 
+or @code{longjmp} and doesn't return.
 
 @smallexample
 void my_obstack_alloc_failed (void)
index 5f6b420f7b3aff0394bab2033af989c470b6838b..f7fe306036bb5fe14d039a331b626dacb2149e05 100644 (file)
@@ -20,6 +20,7 @@ Boston, MA 02110-1301, USA.  */
 
 #include "pex-common.h"
 
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
 #ifdef HAVE_STDLIB_H
@@ -350,7 +351,7 @@ argv_to_cmdline (char *const *argv)
         prevent wasting 2 chars per argument of the CreateProcess 32k char
         limit.  We need only escape embedded double-quotes and immediately
         preceeding backslash characters.  A sequence of backslach characters
-        that is not follwed by a double quote character will not be
+        that is not followed by a double quote character will not be
         escaped.  */
       needs_quotes = 0;
       for (j = 0; argv[i][j]; j++)
@@ -365,7 +366,7 @@ argv_to_cmdline (char *const *argv)
              /* Escape preceeding backslashes.  */
              for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
                cmdline_len++;
-             /* Escape the qote character.  */
+             /* Escape the quote character.  */
              cmdline_len++;
            }
        }
@@ -568,7 +569,8 @@ env_compare (const void *a_ptr, const void *b_ptr)
  * target is not actually an executable, such as if it is a shell script. */
 
 static pid_t
-win32_spawn (const char *executable,
+win32_spawn (struct pex_obj *obj,
+         const char *executable,
             BOOL search,
             char *const *argv,
              char *const *env, /* array of strings of the form: VAR=VALUE */
@@ -576,14 +578,12 @@ win32_spawn (const char *executable,
             LPSTARTUPINFO si,
             LPPROCESS_INFORMATION pi)
 {
-  char *full_executable;
-  char *cmdline;
+  char *full_executable = NULL;
+  char *cmdline = NULL;
+  pid_t pid = (pid_t) -1;
   char **env_copy;
   char *env_block = NULL;
 
-  full_executable = NULL;
-  cmdline = NULL;
-
   if (env)
     {
       int env_size;
@@ -621,13 +621,42 @@ win32_spawn (const char *executable,
 
   full_executable = find_executable (executable, search);
   if (!full_executable)
-    goto error;
+    goto exit;
   cmdline = argv_to_cmdline (argv);
   if (!cmdline)
-    goto error;
-    
-  /* Create the child process.  */  
-  if (!CreateProcess (full_executable, cmdline, 
+    goto exit;
+  /* If cmdline is too large, CreateProcess will fail with a bad
+     'No such file or directory' error. Try passing it through a
+     temporary response file instead.  */
+  if (strlen (cmdline) > 32767)
+    {
+      char *response_file = make_temp_file ("");
+      /* Register the file for deletion by pex_free.  */
+      ++obj->remove_count;
+      obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count);
+      obj->remove[obj->remove_count - 1] = response_file;
+      int fd = pex_win32_open_write (obj, response_file, 0, 0);
+      if (fd == -1)
+        goto exit;
+      FILE *f = pex_win32_fdopenw (obj, fd, 0);
+      /* Don't write argv[0] (program name) to the response file.  */
+      if (writeargv (&argv[1], f))
+        {
+          fclose (f);
+          goto exit;
+        }
+      fclose (f); /* Also closes fd and the underlying OS handle.  */
+      char *response_arg = concat ("@", response_file, NULL);
+      char *response_argv[3] = {argv[0], response_arg, NULL};
+      free (cmdline);
+      cmdline = argv_to_cmdline (response_argv);
+      free (response_arg);
+      if (!cmdline)
+        goto exit;
+    }
+  
+  /* Create the child process.  */
+  if (CreateProcess (full_executable, cmdline,
                      /*lpProcessAttributes=*/NULL,
                      /*lpThreadAttributes=*/NULL,
                      /*bInheritHandles=*/TRUE,
@@ -637,33 +666,25 @@ win32_spawn (const char *executable,
                      si,
                      pi))
     {
-      free (env_block);
-
-      free (full_executable);
-
-      return (pid_t) -1;
+      CloseHandle (pi->hThread);
+      pid = (pid_t) pi->hProcess;
     }
 
+ exit:
   /* Clean up.  */
-  CloseHandle (pi->hThread);
-  free (full_executable);
-  free (env_block);
-
-  return (pid_t) pi->hProcess;
-
- error:
   free (env_block);
   free (cmdline);
   free (full_executable);
-
-  return (pid_t) -1;
+  
+  return pid;
 }
 
 /* Spawn a script.  This simulates the Unix script execution mechanism.
    This function is called as a fallback if win32_spawn fails. */
 
 static pid_t
-spawn_script (const char *executable, char *const *argv,
+spawn_script (struct pex_obj *obj,
+              const char *executable, char *const *argv,
               char* const *env,
              DWORD dwCreationFlags,
              LPSTARTUPINFO si,
@@ -713,20 +734,20 @@ spawn_script (const char *executable, char *const *argv,
              executable = strrchr (executable1, '\\') + 1;
              if (!executable)
                executable = executable1;
-             pid = win32_spawn (executable, TRUE, argv, env,
+             pid = win32_spawn (obj, executable, TRUE, argv, env,
                                 dwCreationFlags, si, pi);
 #else
              if (strchr (executable1, '\\') == NULL)
-               pid = win32_spawn (executable1, TRUE, argv, env,
+               pid = win32_spawn (obj, executable1, TRUE, argv, env,
                                   dwCreationFlags, si, pi);
              else if (executable1[0] != '\\')
-               pid = win32_spawn (executable1, FALSE, argv, env,
+               pid = win32_spawn (obj, executable1, FALSE, argv, env,
                                   dwCreationFlags, si, pi);
              else
                {
                  const char *newex = mingw_rootify (executable1);
                  *avhere = newex;
-                 pid = win32_spawn (newex, FALSE, argv, env,
+                 pid = win32_spawn (obj, newex, FALSE, argv, env,
                                     dwCreationFlags, si, pi);
                  if (executable1 != newex)
                    free ((char *) newex);
@@ -736,7 +757,7 @@ spawn_script (const char *executable, char *const *argv,
                      if (newex != executable1)
                        {
                          *avhere = newex;
-                         pid = win32_spawn (newex, FALSE, argv, env,
+                         pid = win32_spawn (obj, newex, FALSE, argv, env,
                                             dwCreationFlags, si, pi);
                          free ((char *) newex);
                        }
@@ -755,7 +776,7 @@ spawn_script (const char *executable, char *const *argv,
 /* Execute a child.  */
 
 static pid_t
-pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
+pex_win32_exec_child (struct pex_obj *obj, int flags,
                      const char *executable, char * const * argv,
                       char* const* env,
                      int in, int out, int errdes,
@@ -851,10 +872,10 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
   si.hStdError = stderr_handle;
 
   /* Create the child process.  */  
-  pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0,
+  pid = win32_spawn (obj, executable, (flags & PEX_SEARCH) != 0,
                     argv, env, dwCreationFlags, &si, &pi);
   if (pid == (pid_t) -1)
-    pid = spawn_script (executable, argv, env, dwCreationFlags,
+    pid = spawn_script (obj, executable, argv, env, dwCreationFlags,
                         &si, &pi);
   if (pid == (pid_t) -1)
     {
index c6f68495a33d124cec901251812150c52e2d0ea3..49209e8229ffb44259877c446985fd73b4f58c31 100644 (file)
@@ -18,18 +18,23 @@ length, the function returns @var{string}.
 
 #include <stddef.h>
 
-extern int memcmp (const void *, const void *, size_t);
+extern char *strchr (const char *, int);
+extern int strncmp (const void *, const void *, size_t);
 extern size_t strlen (const char *);
 
 char *
 strstr (const char *s1, const char *s2)
 {
+  const char *p = s1;
   const size_t len = strlen (s2);
-  while (*s1)
+
+  if (!len)
+    return s1;
+
+  for (; (p = strchr (p, *s2)) != 0; p++)
     {
-      if (!memcmp (s1, s2, len))
-       return (char *)s1;
-      ++s1;
+      if (strncmp (p, s2, len) == 0)
+       return (char *)p;
     }
   return (0);
 }
index d9bc7ed4b1fc33fde1c683202f9e4fd7fbb7e40c..0acd2d635db048a1594ddf0282cc72313593ae9c 100644 (file)
@@ -1659,3 +1659,33 @@ auto f()::{lambda<typename $T0>(X<$T0>*, X<int>*)#1}::operator()<char>(X<char>*,
 
 _ZZN1XIiE1FEvENKUliE_clEi
 X<int>::F()::{lambda(int)#1}::operator()(int) const
+
+_Z1fIiEv1AIXnxtlT_EEE
+void f<int>(A<noexcept(int{})>)
+
+_ZNO1Ycv1XEv
+Y::operator X() &&
+
+_ZNO1Ycv1XIT_EIvEEv
+Y::operator X<void><void>() &&
+
+_ZNO1Y3bobEv
+Y::bob() &&
+
+_ZNR1Y3bobEv
+Y::bob() &
+
+_ZNKR1YcvRK1XIT_EIvEEv
+Y::operator X<void> const&<void>() const &
+
+_ZZN1XIiEcviEvE1y
+X<int>::operator int()::y
+
+_ZZN1XIiEcv1ZIiEEvE1y
+X<int>::operator Z<int>()::y
+
+_ZZN1Xcv1ZIT_EIiEEvE1y
+X::operator Z<int><int>()::y
+
+_ZZN1XIfEcv1ZIT_EIiEEvE1y
+X<float>::operator Z<int><int>()::y